package com.sq.universe.flowable.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sq.universe.base.ann.FlowableAnn;
import com.sq.universe.base.dao.BaseDao;
import com.sq.universe.base.entity.FlowableEntity;
import com.sq.universe.base.utils.AuthUtils;
import com.sq.universe.flowable.entity.TaskEntity;
import com.sq.universe.flowable.entity.WorkflowEntity;
import com.sq.universe.flowable.service.WorkflowService;
import com.sq.universe.system.entity.MenuEntity;
import com.sq.universe.system.entity.UserEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.xmlbeans.impl.xb.xsdschema.Public;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.*;
import org.flowable.engine.form.TaskFormData;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricActivityInstanceQuery;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.form.engine.FormEngine;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class WorkflowServiceimpl implements WorkflowService {

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private BaseDao baseDao;

    @Autowired
    private FormService formService;

    @Autowired
    private FormEngine formEngine;

    @Autowired
    private RepositoryService repositoryService;


    /**
     * 查询表单
     * @param formKey
     * @return
     */
    public TaskFormData getForm(String formKey){
        return formService.getTaskFormData(formKey);
    }


    /**
     * 查询任务列表
     * @return
     */
    public List<Task> queryTask(){
        return taskService.createTaskQuery().list();
    }

    /**
     * 查询待办事项
     * @param userEntity
     * @return
     */
    public PageInfo queryTodo(UserEntity userEntity,WorkflowEntity workflowEntity){
        if(userEntity == null){
            userEntity = new UserEntity();
        }
        String  userRoles =  userEntity.getUserRoles();
        List<String> roleList = new ArrayList<>();
        for (String role : userRoles.split(",")){
            roleList.add(role);
        }
        TaskQuery taskQuery = taskService.createTaskQuery().active().includeProcessVariables();
        TaskQuery countQuery = taskService.createTaskQuery().active().includeProcessVariables();
        if(workflowEntity.getProcessParam() != null){
           for(String key :  workflowEntity.getProcessParam().keySet()){
               String value = workflowEntity.getProcessParam().get(key) == null ? "" : workflowEntity.getProcessParam().get(key).toString();
               if(StringUtils.isNotBlank(value)){
                   taskQuery.processVariableValueLike(key,"%" + value  +"%" );
                   countQuery.processVariableValueLike(key,"%" + value  +"%");
               }
           }
        }
        Integer start = ( workflowEntity.getPageNo() - 1) * workflowEntity.getPageSize();
        Integer end = ( workflowEntity.getPageNo() ) * workflowEntity.getPageSize();
        List<Task> result = taskQuery.or().taskCandidateGroupIn(roleList).taskCandidateOrAssigned(userEntity.getUserId().toString()).listPage(start,end);
        long total = countQuery.or().taskCandidateGroupIn(roleList).taskAssignee(userEntity.getUserId().toString()).count();
        List<TaskEntity> list = new ArrayList();
        for(Task task : result){
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().includeProcessVariables().processInstanceId(task.getProcessInstanceId()).singleResult();
            TaskEntity taskEntity = new TaskEntity();
            taskEntity.setTaskId(task.getId());
            taskEntity.setProcessDefinitionKey( processInstance.getProcessDefinitionKey());
            taskEntity.setTaskName(task.getName());
            taskEntity.setCreateTime(task.getCreateTime());
            taskEntity.setPocessInstanceId(task.getProcessInstanceId());
            taskEntity.setDescription(task.getDescription());
            taskEntity.setTaskFormKey(task.getFormKey());
            taskEntity.setProcessVariables(processInstance.getProcessVariables());
            taskEntity.setTaskLocalVariables(task.getTaskLocalVariables());
            taskEntity.setDueDate(task.getDueDate());
            taskEntity.setBussinessKey(processInstance.getBusinessKey());
            list.add(taskEntity);
        }
        PageInfo pageInfo = new PageInfo(list);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(workflowEntity.getPageNo());
        pageInfo.setPages(workflowEntity.getPageSize());
        return pageInfo ;
    }

    public String queryTaskId(String processInstanceId){
        UserEntity userEntity = AuthUtils.getCurrentUser();
        String  userRoles =  userEntity.getUserRoles();
        List<String> roleList = new ArrayList<>();
        for (String role : userRoles.split(",")){
            roleList.add(role);
        }
        TaskQuery taskQuery = taskService.createTaskQuery().active().includeProcessVariables();
        Task task = taskQuery.or().taskCandidateGroupIn(roleList).taskCandidateOrAssigned(userEntity.getUserId().toString()).endOr().processInstanceId(processInstanceId).singleResult();
        if(task != null){
            return task.getId();
        }else {
            return "";
        }
    }

    public Map<String,String> queryTaskInfo(String processInstanceId){
        UserEntity userEntity = AuthUtils.getCurrentUser();
        String  userRoles =  userEntity.getUserRoles();
        List<String> roleList = new ArrayList<>();
        for (String role : userRoles.split(",")){
            roleList.add(role);
        }
        TaskQuery taskQuery = taskService.createTaskQuery().active().includeProcessVariables();
        Task task = taskQuery.processInstanceId(processInstanceId).singleResult();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().includeProcessVariables().processInstanceId(processInstanceId).singleResult();
        Map taskInfo = new HashMap();
        taskInfo.put("businessKey",processInstance.getBusinessKey());
        if(task != null){
            taskInfo.put("taskId",task.getId());
            taskInfo.put("taskName",task.getName());

        }
        return taskInfo;
    }


    /**
     * 查询全部的任务列表
     * @param userEntity
     * @return
     */
    public PageInfo taskList(UserEntity userEntity,WorkflowEntity workflowEntity){
        if(userEntity == null){
            userEntity = new UserEntity();
        }
        String  userRoles =  userEntity.getUserRoles();
        List<String> roleList = new ArrayList<>();
        for (String role : userRoles.split(",")){
            roleList.add(role);
        }
        List<Task> taskList = taskService.createTaskQuery().includeProcessVariables().or().taskCandidateGroupIn(roleList).taskAssignee(userEntity.getUserId().toString()).list();
        long total = taskService.createTaskQuery().includeProcessVariables().or().taskCandidateGroupIn(roleList).taskAssignee(userEntity.getUserId().toString()).count();
        List<TaskEntity> list = new ArrayList();
        for(Task task : taskList){
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().includeProcessVariables().processInstanceId(task.getProcessInstanceId()).singleResult();
            TaskEntity taskEntity = new TaskEntity();
            taskEntity.setTaskId(task.getId());
            taskEntity.setTaskName(task.getName());
            taskEntity.setCreateTime(task.getCreateTime());
            taskEntity.setPocessInstanceId(task.getProcessInstanceId());
            taskEntity.setDescription(task.getDescription());
            taskEntity.setTaskFormKey(task.getFormKey());
            taskEntity.setProcessVariables(processInstance.getProcessVariables());
            taskEntity.setTaskLocalVariables(task.getTaskLocalVariables());
            taskEntity.setDueDate(task.getDueDate());
            taskEntity.setBussinessKey(processInstance.getBusinessKey());
            list.add(taskEntity);
        }
        PageInfo pageInfo = new PageInfo(list);
        pageInfo.setTotal(total);
        return pageInfo ;
    }

    /**
     * 查询已处理任务列表
     * @param userEntity
     * @return
     */
    public PageInfo queryDone(UserEntity userEntity, WorkflowEntity workflowEntity){
        if(userEntity == null){
            userEntity = new UserEntity();
        }
        String  userRoles =  userEntity.getUserRoles();
        List<String> roleList = new ArrayList<>();
        for (String role : userRoles.split(",")){
            roleList.add(role);
        }
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().or().
                taskAssignee(userEntity.getUserId() + "").taskCandidateGroupIn(roleList).list();
        PageInfo pageInfo = new PageInfo(historicTaskInstanceList);
        return pageInfo ;
    }

    /**
     * 启动任务
     * @param workflowEntity
     * @param userEntity
     */
    public void start(WorkflowEntity workflowEntity,UserEntity userEntity){
        try {
            FlowableEntity flowableEntity = workflowEntity.getFlowableEntity();
            workflowEntity.getParams().put("startUserName",userEntity.getUserName());
            workflowEntity.getParams().put("taskName","启动");
            workflowEntity.getParams().put("userId",userEntity.getUserId());
            workflowEntity.getParams().put("userName",userEntity.getUserName());
            ProcessInstance processInstance;
            Authentication.setAuthenticatedUserId(userEntity.getUserId().toString());
            processInstance = runtimeService.startProcessInstanceByKey(flowableEntity.getProcDefKey(), workflowEntity.getBussinessKey(),  workflowEntity.getParams());
            Authentication.setAuthenticatedUserId(null);
            List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();
            String state = "";
            for(Task task : tasks){
                if(StringUtils.isBlank(state)){
                    state = task.getName();
                }else{
                    state += "," +  task.getName();
                }
            }
            String sql = "update " + flowableEntity.getTableName()
                    +  " set " + flowableEntity.getProcInstColumn() + "=" + processInstance.getId()
                    + "," + flowableEntity.getNodeColumn() + "='" + state + "'"
                    + " where " + flowableEntity.getTableId() + "=" + workflowEntity.getBussinessKey();
            baseDao.executeSql(sql);
        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    /**
     * 完成任务
     */
    public void completeTask(WorkflowEntity workflowEntity,UserEntity userEntity){
        workflowEntity.getParams().put("userId",userEntity.getUserId());
        workflowEntity.getParams().put("userName",userEntity.getUserName());
        if(StringUtils.isBlank(workflowEntity.getComment())){
            workflowEntity.setComment("");
        }
        Task task = taskService.createTaskQuery().taskId(workflowEntity.getTaskId()).singleResult();
        taskService.claim(workflowEntity.getTaskId(),userEntity.getUserId() + "");
        taskService.addComment(workflowEntity.getTaskId(), workflowEntity.getProcessInstanceId(), workflowEntity.getComment());
        if( workflowEntity.getOutcome() == null){
            workflowEntity.getParams().put("outcome","");
        }
        // 流程变量
        taskService.setVariables(workflowEntity.getTaskId(),workflowEntity.getProcessParam());
        taskService.complete(workflowEntity.getTaskId(),  workflowEntity.getParams());
        sendMessage(task.getProcessInstanceId());
    }

    /**
     * 退回
     */
    public void rollback(WorkflowEntity workflowEntity, UserEntity userEntity  ){
        HistoricTaskInstance hisTask = historyService
                .createHistoricTaskInstanceQuery().taskId(workflowEntity.getTaskId())
                .singleResult();
        List<HistoricTaskInstance> historyList = historyService.createHistoricTaskInstanceQuery().processInstanceId(workflowEntity.getProcessInstanceId()).list();
        for(int i = 0 ;  i < historyList.size() ; i++){
            if(hisTask.getName().equals(historyList.get(i).getName())){
                if( i >= 1){
                    hisTask = historyList.get(i - 1);
                }else{
                    hisTask = historyList.get(1);
                }
                break;
            }
        }
//        hisTask = historyList.get(historyList.size() - 2);
        Task task = taskService.createTaskQuery().taskId(workflowEntity.getTaskId()).singleResult();
        workflowEntity.getParams().put("userId",userEntity.getUserId());
        workflowEntity.getParams().put("userName",userEntity.getUserName());
        taskService.setVariablesLocal(task.getId(),workflowEntity.getParams());
        taskService.setVariables(workflowEntity.getTaskId(),workflowEntity.getProcessParam());
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(workflowEntity.getProcessInstanceId())
                .moveActivityIdTo(task.getTaskDefinitionKey(), hisTask.getTaskDefinitionKey())
                .changeState();
    }

    public List history(WorkflowEntity workflowEntity){
        List<HistoricActivityInstance> list =  ((HistoricActivityInstanceQuery) ((HistoricActivityInstanceQuery) historyService.createHistoricActivityInstanceQuery().processInstanceId(workflowEntity.getProcessInstanceId())
                .orderByHistoricActivityInstanceStartTime().asc()).orderByHistoricActivityInstanceEndTime()
                .asc()).list();
        List mapList = new ArrayList<>();
        List<HistoricVariableInstance> var = historyService.createHistoricVariableInstanceQuery()
                .processInstanceId(workflowEntity.getProcessInstanceId()).list();
        Map _map = new HashMap();

        for (int i = 0; i < var.size(); i++) {
            HistoricVariableInstance v = var.get(i);
            _map.put(v.getVariableName(), v.getValue());
        }
        for(HistoricActivityInstance histIns : list){

            Map  map = new HashMap();
            if(StringUtils.isBlank(histIns.getActivityName())){
                continue;
            }
            if (StringUtils.isNotBlank(histIns.getActivityName()) && StringUtils.isBlank(histIns.getTaskId())){
                map.put("startTime", histIns.getStartTime());
                map.put("endTime", histIns.getEndTime());
                map.put("taskName", histIns.getActivityName());
                map.put("variables",_map);
                mapList.add(map);
                continue;
            }
            HistoricTaskInstance hisTask = historyService.createHistoricTaskInstanceQuery().taskId(histIns.getTaskId()).singleResult();

            map.put("taskId", histIns.getTaskId());
            map.put("taskName", histIns.getActivityName());
            map.put("startTime", histIns.getStartTime());
            map.put("endTime", histIns.getEndTime());
            map.put("processDefinitionId", histIns.getProcessDefinitionId());
            map.put("processInstanceId", histIns.getProcessInstanceId());
            map.put("assignee", histIns.getAssignee());
            map.put("taskFormKey", hisTask.getFormKey());
            map.put("comment", taskService.getTaskComments(histIns.getTaskId()));
            histIns.getExecutionId();
            //查询每个任务节点的参数
            List<HistoricVariableInstance> taskVariables = historyService.createHistoricVariableInstanceQuery().taskId(histIns.getTaskId()).list();
            Map taskVarMap = new HashMap();
            for (int i = 0; i < taskVariables.size(); i++) {
                HistoricVariableInstance v = taskVariables.get(i);
                taskVarMap.put(v.getVariableName(), v.getValue());
            }
            map.put("variables",taskVarMap);

            mapList.add(map);
        }

        return mapList;
    }

    public void sendMessage(String processInstanceId){
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        for(Task task : taskList){
            log.error("下一个任务： " + task.getName());
            task.getAssignee();
        }
    }


}
